﻿using System;
using System.Collections.Generic;
using System.Text;

namespace GIALib
{
    /// <summary>
    /// Contains the relationship logic rules for adding people and how they relate to each other.
    /// </summary>
    public static class RelationshipHelper
    {
        /// <summary>
        /// Adding the junior relationship between the person and the junior.
        /// </summary>
        /// <param name="group">group</param>
        /// <param name="person">the person who has the junior</param>
        /// <param name="junior">junior to be had</param>
        public static void AddJunior(PeopleCollection group, Person person, Person junior)
        { 
            //Add the new junior as a workmate to any existirng juniors
            foreach (Person existingJunior in person.Juniors)
            {
                group.AddWorkmate(existingJunior, junior);
            }
            //Add the junior to the person
            group.AddJunior(person, junior, SeniorJuniorModifier.Natural);
        }

        /// <summary>
        /// Adding the senior relationship between the person and the senior.
        /// </summary>
        /// <param name="group">group</param>
        /// <param name="person">the person who has the senior</param>
        /// <param name="senior">the senior</param>
        public static void AddSenior(PeopleCollection group, Person person, Person senior)
        { 
            //A person can only have 1 senior
            if (person.Seniors.Count == 1)
                return;

            //Add the senior to the main collection of people.
            group.Add(senior);

            group.AddJunior(senior, person, SeniorJuniorModifier.Natural);
            
            //Handle the workmates of the person
            if (person.Workmates.Count > 0)
            {
                //Make workmates the junior of the new senior.
                foreach (Person workmate in person.Workmates)
                {
                    group.AddJunior(senior, workmate, SeniorJuniorModifier.Natural);
                }
            }

            //Setter for property change notification
            person.HasSeniors = true;
        }

        /// <summary>
        /// Return a list of juniors for the senior.
        /// </summary>
        /// <param name="senior">the senior who has juniors</param>
        /// <returns>list of juniors</returns>
        private static List<Person> GetJuniors(Person senior)
        {
            //Get list of the senior.
            List<Person> juniors = new List<Person>(senior.Juniors);

            return juniors;
        }

        /// <summary>
        /// Add a workmate for the person.
        /// </summary>
        /// <param name="group">group</param>
        /// <param name="person">the person who has the workmate</param>
        /// <param name="workmate">the workmate</param>
        public static void AddWorkmate(PeopleCollection group, Person person, Person workmate)
        { 
            //Handle workmates
            if (person.Workmates.Count > 0)
            { 
                //Make the workmates to each other.
                foreach (Person existingWorkmate in person.Workmates)
                {
                    group.AddWorkmate(existingWorkmate, workmate);
                }
            }

            if (person.Seniors != null)
            {
                group.AddWorkmate(person, workmate);
                group.AddJunior(person.Seniors[0], workmate, SeniorJuniorModifier.Natural);
            }
        }

        /// <summary>
        /// Change the person's senior
        /// </summary>
        /// <param name="group">group</param>
        /// <param name="person">the person who's senior will be changed</param>
        /// <param name="newSenior">the new senior</param>
        public static void ChangeSenior(PeopleCollection group, Person person, Person newSenior)
        { 
            //Don't do anything if there is nothing to change or if the senior is the same
            if (person.Senior == null || newSenior == null || person.Senior.Equals(newSenior))
                return;

            //Store the current senior which will be removed.
            Person formerSenior = person.Senior;

            //Remove the senior.
            RemoveSeniorJuniorRelationship(person, formerSenior);

            //Remove the workmate relationships
            RemoveWorkmateRelationships(person);

            //Add the new senior.
            AddSenior(group, person, newSenior);
        }

        /// <summary>
        /// Helper function for removing workmates relationships.
        /// </summary>
        /// <param name="person">the person who's workmates will be removed</param>
        private static void RemoveWorkmateRelationships(Person person)
        {
            for (int i = person.Relationships.Count - 1; i >= 0; i--)
            {
                if (person.Relationships[i].RelationshipType == RelationshipType.Workmate)
                {
                    person.Relationships.RemoveAt(i);
                }
            }
        }

        /// <summary>
        /// Helper function for removing a senior relationship
        /// </summary>
        /// <param name="person">the person who has a senior</param>
        /// <param name="senior">the senior who will be removed</param>
        private static void RemoveSeniorJuniorRelationship(Person person, Person senior)
        { 
            foreach(Relationship relationship in person.Relationships)
            {
                if(relationship.RelationshipType == RelationshipType.Senior && relationship.RelationTo.Equals(senior))
                {
                    person.Relationships.Remove(relationship);
                    break;
                }
            }

            foreach (Relationship relationship in senior.Relationships)
            {
                if (relationship.RelationshipType == RelationshipType.Junior && relationship.RelationTo.Equals(person))
                {
                    senior.Relationships.Remove(relationship);
                    break;
                }
            }
        }

        /// <summary>
        /// Performs the business logic for changing the deleting the person
        /// </summary>
        public static void DeletePerson(PeopleCollection group, Person personToDelete)
        {
            if (!personToDelete.IsDeletable)
                return;

            // Remove the personToDelete from the relationships that contains the personToDelete.
            foreach (Relationship relationship in personToDelete.Relationships)
            {
                foreach (Relationship rel in relationship.RelationTo.Relationships)
                {
                    if (rel.RelationTo.Equals(personToDelete))
                    {
                        relationship.RelationTo.Relationships.Remove(rel);
                        break;
                    }
                }
            }

            // Delete the person's photos and resume.
            personToDelete.DeletePhotos();
            personToDelete.DeleteResume();

            group.Remove(personToDelete);
        }
    }
}

